#ifndef GAMEENGINE_CORE_GRAPH_LINK_HPP
#define GAMEENGINE_CORE_GRAPH_LINK_HPP

#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//! Default constructor
/*!
 @param node1 A pointer to the first node
 @param node2 A pointer to the second node
 */
template <class N, class T>
GraphLink<N,T>::GraphLink(N_pointer node1, N_pointer node2) :
	node1_(node1), node2_(node2) {}

//! Constructor
/*!
 @param value The value associated to this link
 @param node1 A pointer to the first node
 @param node2 A pointer to the second node
 */
template <class N, class T>
GraphLink<N,T>::GraphLink(const T& value, N_pointer node1, N_pointer node2) :
	value_(value), node1_(node1), node2_(node2) {}

//! Copy constructor
/*!
 @param rhs The link to copy
 @note Class T should have a copy constructor
 */
template <class N, class T>
GraphLink<N,T>::GraphLink(const GraphLink& rhs) :
	value_(rhs.value_), node1_(rhs.node1_), node2_(rhs.node2_) {}

//! Destructor
template <class N, class T>
GraphLink<N,T>::~GraphLink() {}

//! Assignment operator
/*!
 @param rhs The link to copy
 @note Class T should have an assignment operator
 */
template <class N, class T>
GraphLink<N,T>& GraphLink<N,T>::operator=(const GraphLink& rhs) {
	if ( &rhs != this ) {
		value_ = rhs.value_;
		node1_ = rhs.node1_;
		node2_ = rhs.node2_;
	}
	return *this;
}

//! Accessor to the value associated to the node (read-write)
/*!
 @return A reference to the value associated to the node
 */
template <class N, class T>
T& GraphLink<N,T>::value() {
	return value_;
}

//! Inferior operator
/*!
 @param rhs The link to compare
 @return True if the other link is inferior to the current link, false otherwise
 @note Type T should have an inferior operator
 */
template <class N, class T>
bool GraphLink<N,T>::operator<(const GraphLink& rhs) const {
	return ( value_ < rhs.value_ );
}

//! Accessor to the value associated to the node (read only)
/*!
 @return A constant reference to the value associated to the node
 */
template <class N, class T>
const T& GraphLink<N,T>::value() const {
	return value_;
}

//! Check if the link contains the given node
/*!
 @param node A pointer to the node to be checked
 @return True if the link contains the node, false otherwise
 @note This function is based on pointer comparison
 */
template <class N, class T>
bool GraphLink<N,T>::contains(const N_pointer node) const {
	return ( ( node1_ == node ) || ( node2_ == node ) );
}

//! Get the neighbour of given node
/*!
 @param node A pointer to the node of which we want to find the neighbour
 @return The neighbour node. May be nil if no neighbour was
         found in the link.
 */
template <class N, class T>
typename GraphLink<N,T>::N_pointer GraphLink<N,T>::get_neighbour(const N_pointer node) const {
	if ( node1_ == node ) return node2_;
	if ( node2_ == node ) return node1_;
	return nil;
}

//! Accessor to the first node (read only)
/*!
 @return A pointer to the first node
 */
template <class N, class T>
typename GraphLink<N,T>::N_pointer GraphLink<N,T>::node1() const {
	return node1_;
}

//! Accessor to the first node (read-write)
/*!
 @return A reference to the first node pointer
 */
template <class N, class T>
typename GraphLink<N,T>::N_pointer& GraphLink<N,T>::node1() {
	return node1_;
}

//! Accessor to the second node (read only)
/*!
 @return A pointer to the second node
 */
template <class N, class T>
typename GraphLink<N,T>::N_pointer GraphLink<N,T>::node2() const {
	return node2_;
}

//! Accessor to the second node (read-write)
/*!
 @return A reference to the second node pointer
 */
template <class N, class T>
typename GraphLink<N,T>::N_pointer& GraphLink<N,T>::node2() {
	return node2_;
}

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#endif
